/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.manager.monitor;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edi.Constant;
import com.edi.Kola;
import com.edi.client.plugin.Plugin;
import com.edi.client.plugin.ScriptPlugin;
import com.edi.exceptions.EdiException;
import com.edi.manager.PluginManager;
import com.edi.util.dynacode.DynaComplier;

/**
 * 查看并监控脚本插件目录，进行插件的编译和加载 1、获得所有插件源文件，判断有无class类 2、判断有无被注册 3、判断是否过期
 * 
 * 
 */
public class ScriptPluginMonitor implements Runnable {
	private static Log log = LogFactory.getLog(ScriptPluginMonitor.class); 

	private boolean running = false;

	DynaComplier dynaComplier;

	private PluginManager pluginManager;
	
	private boolean workareaExist;

	public ScriptPluginMonitor(PluginManager pluginManager) {
		super();
		this.pluginManager = pluginManager;
		dynaComplier = new DynaComplier();
		File srcDir = new File(System.getProperty(Constant.EDIPATH)
				+ Kola.SCRIPTPLUGIN_DIR);
		
		//修改：增加额外classpath ，用于java文件编译   cya 2009-3-18
		StringBuffer extraJARs=new StringBuffer();
		File extraJARFiles= new File(System.getProperty(Constant.EDIPATH)+Kola.SCRIPTPLUGIN_DIR+"/lib/");
//		log.debug(" extraJARFiles ="+extraJARFiles.exists());
		if(extraJARFiles.exists()){
			workareaExist = true;
			File[] jarFiles=extraJARFiles.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					String fileName = pathname.getName().toLowerCase();
					return fileName.endsWith(".jar");
				}
			});
			for(int i=0;i<jarFiles.length;i++){ 
				if(extraJARs.length()>0)
					extraJARs.append(File.pathSeparatorChar);
				extraJARs.append(StringUtils.replaceOnce(jarFiles[i].toURI().toString(), "file:", ""));
			}
		}
//		log.debug(" extraJARs ="+extraJARs);
		//修改结束
		dynaComplier.addSourceDir(srcDir,extraJARs.toString());
	}
	
	public void firstRun(){
		try {
			System.out.println("asfdasfasdfasdf");
			String pluginDir = System.getProperty(Constant.EDIPATH)
					+ Kola.SCRIPTPLUGIN_DIR;

			File pluginDirectory = new File(pluginDir);
			//log.debug(" pluginDirectory ="+pluginDirectory  +" pluginDirectory exit ="+pluginDirectory.exists());

			File[] javaFiles = pluginDirectory.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					String fileName = pathname.getName().toLowerCase();
					return fileName.endsWith(".java");
				}
			});
			//log.debug(" javaFiles ="+javaFiles.length);

			/**
			 * 检查文件编译步骤： 1、java文件有无对应的class文件，没有则编译
			 * 2、有class文件，PluginManager有无记录，没有则添加插件
			 * 3、java文件日期与class日期比较，判断是否应该重新编译
			 */

			for (File javaFile : javaFiles) {
				//log.debug("enter /////////////////////////////////////////////////////// plugin  ="+javaFile.getName());
				String className = StringUtils.substringBefore(javaFile
						.getName(), ".java");
				String classFileName = className + ".class";
				File classFile = new File(javaFile.getParent(),classFileName);
				//log.debug(" classFile ="+classFile.getAbsolutePath()+" classFile.exists() ="+classFile.exists());
				// 无对应的class文件，编译后加载
				if (!classFile.exists()) {
					Class clazz = dynaComplier.loadClass(className);
					log.debug("clazz ="+clazz.getName());
					Plugin scirptPlugin = new ScriptPlugin(clazz,true);
					pluginManager.addScriptPlugin(scirptPlugin);
				}else if (classFile.lastModified()<javaFile.lastModified()){
					// 表明java文件已被修改，需要重新编译
					log.debug(" class 存在 已经被更新");
					Plugin scriptPlugin = pluginManager.getScriptPluginByName(StringUtils.substringBefore(javaFile
							.getName(), ".java"));		
					log.debug(" scriptPlugin ==null "+(scriptPlugin==null));
					if (scriptPlugin != null){
						pluginManager.removeScriptPlugin(scriptPlugin.getName());
						scriptPlugin.dispose();
					}
					Class clazz = dynaComplier.loadClass(className);
					Method[] methods=clazz.getMethods();
					log.debug(" methods size ="+(methods==null?0:methods.length));
					for(Method m:methods){
						log.debug(" Method name= "+m.getName());
					}
					scriptPlugin = new ScriptPlugin(clazz,true);
					pluginManager.addScriptPlugin(scriptPlugin);
				}else{
					//有class文件，并且未作更新,则仅查看插件有无被管理
					//log.debug(" class 存在 没有被更新");
					Plugin scriptPlugin = pluginManager.getScriptPluginByName(StringUtils.substringBefore(javaFile
							.getName(), ".java"));
					//log.debug(" scriptPlugin ==null  ////"+(scriptPlugin==null));
					if (scriptPlugin == null){
						Class clazz = dynaComplier.loadClass(className);
						scriptPlugin = new ScriptPlugin(clazz,true);
						pluginManager.addScriptPlugin(scriptPlugin);
					}
				}
//				log.debug("end /////////////////////////////////////////////////////// plugin  ="+javaFile.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
			EdiException exception=new EdiException("编译java文件发生异常！", e);			
			log.error(exception.getMessage());
		}
	}

	public void run() {
//		log.debug(" enter ScriptPluginMonitor run ");
		
		synchronized (this) {
			//log.debug(" enter ScriptPluginMonitor running  "+running);
			if (running) {
				return;
			}
			if(!workareaExist)
				return;
			running = true;
		}
		try {

			String pluginDir = System.getProperty(Constant.EDIPATH)
					+ Kola.SCRIPTPLUGIN_DIR;

			File pluginDirectory = new File(pluginDir);
			//log.debug(" pluginDirectory ="+pluginDirectory  +" pluginDirectory exit ="+pluginDirectory.exists());

			File[] javaFiles = pluginDirectory.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					String fileName = pathname.getName().toLowerCase();
					return fileName.endsWith(".java");
				}
			});
			//log.debug(" javaFiles ="+javaFiles.length);

			/**
			 * 检查文件编译步骤： 1、java文件有无对应的class文件，没有则编译
			 * 2、有class文件，PluginManager有无记录，没有则添加插件
			 * 3、java文件日期与class日期比较，判断是否应该重新编译
			 */

			for (File javaFile : javaFiles) {
				//log.debug("enter /////////////////////////////////////////////////////// plugin  ="+javaFile.getName());
				String className = StringUtils.substringBefore(javaFile
						.getName(), ".java");
				String classFileName = className + ".class";
				File classFile = new File(javaFile.getParent(),classFileName);
				//log.debug(" classFile ="+classFile.getAbsolutePath()+" classFile.exists() ="+classFile.exists());
				// 无对应的class文件，编译后加载
				if (!classFile.exists()) {
					Class clazz = dynaComplier.loadClass(className);
					log.debug("clazz ="+clazz.getName());
					Plugin scirptPlugin = new ScriptPlugin(clazz,true);
					pluginManager.addScriptPlugin(scirptPlugin);
				}else if (classFile.lastModified()<javaFile.lastModified()){
					// 表明java文件已被修改，需要重新编译
					log.debug(" class 存在 已经被更新");
					Plugin scriptPlugin = pluginManager.getScriptPluginByName(StringUtils.substringBefore(javaFile
							.getName(), ".java"));		
					log.debug(" scriptPlugin ==null "+(scriptPlugin==null));
					if (scriptPlugin != null){
						pluginManager.removeScriptPlugin(scriptPlugin.getName());
						scriptPlugin.dispose();
					}
					Class clazz = dynaComplier.loadClass(className);
					Method[] methods=clazz.getMethods();
					log.debug(" methods size ="+(methods==null?0:methods.length));
					for(Method m:methods){
						log.debug(" Method name= "+m.getName());
					}
					scriptPlugin = new ScriptPlugin(clazz,true);
					pluginManager.addScriptPlugin(scriptPlugin);
				}else{
					//有class文件，并且未作更新,则仅查看插件有无被管理
					//log.debug(" class 存在 没有被更新");
					Plugin scriptPlugin = pluginManager.getScriptPluginByName(StringUtils.substringBefore(javaFile
							.getName(), ".java"));
					//log.debug(" scriptPlugin ==null  ////"+(scriptPlugin==null));
					if (scriptPlugin == null){
						Class clazz = dynaComplier.loadClass(className);
						scriptPlugin = new ScriptPlugin(clazz,true);
						pluginManager.addScriptPlugin(scriptPlugin);
					}
				}
//				log.debug("end /////////////////////////////////////////////////////// plugin  ="+javaFile.getName());
			}

			synchronized (this) {
				running = false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			synchronized (this) {
				running = false;
			}		//修改 ：如果捕获错误，running=false，cya  2009-3-18
			EdiException exception=new EdiException("编译java文件发生异常！", e);			
			log.error(exception.getMessage());
		}
		
	}
}
